If we consider the case where the application is compiled from the source language into an intermediate code, and where this intermediate code is executed by a virtual machine on the chosen target, which is generally the case with the language Java™, there is a problem of a performance level of the execution of the application. FIG. 1 describes the general principle of a code execution technique based on a virtual machine. The source code 100 is compiled into an intermediate code 102 by means of the compiler 101. Then, this code is executed on a virtual machine 103, which is itself executed on the operating system 104, itself executed on a hardware platform 105. Since the intermediate code should be able to get executed on any platform whatsoever that has a virtual machine adapted to the intermediate code, this
intermediate code is not optimized.
In a context of optimizing the performance of the intermediate code, two general optimizing techniques can be distinguished in the prior art.
In the first technique, a compilation of the intermediate code is done dynamically. This is called dynamic compilation. To this end, the virtual machine comprises a compiler capable of dynamically compiling portions of intermediate code into binary mode and also comprises a mechanism to dynamically execute the binary code generated by this compiler instead of the original intermediate code. Thus, the execution of the application consists of a mixture of intermediate code and dynamically generated binary code.
Two major types of embodiments of dynamic compilation can be distinguished: the “just-in-time” (JIT) type and the “dynamic adaptive compiler” (DAC) type.
The “just-in-time” compiler generally has compilation granularity at the method level (it can compile only entire methods). It carries out the compilation in binary code of the method to be executed during the first execution of the method. The dynamic adaptive compiler (DAC) implements another strategy. It executes the application on the virtual machine and dynamically determines the parts of the code penalizing the performance of the application. These parts are called hot spots of the application. Each DAC has its own hot-point detection strategy. These hot spots are constituted, for example, by the most frequently executed methods or the methods comprising loops or the methods taking the greatest amount of time to be executed. Once this identification is done, it compiles the hot spots into binary code. Then, the virtual machine executes the binary code version of the hot spots.
Referring to FIG. 2, we present the general principle of the compilation and execution of an application by means of a virtual machine in combining a dynamic compiler in order to accelerate the execution of the application.
A source software application (100) is drafted by an application developer. This source program comprises computer program instructions written in a source programming language. The source program (100) undergoes a first phase of compilation by a compiler (101) which leads to its conversion into an intermediate program (102). This intermediate program (102) is executed by a virtual machine (103) which gets executed above an operating system (104) in binary mode, that relies on a hardware platform (105). This virtual machine (103) is coupled to a dynamic compiler (106) which automatically determines and dynamically compiles portions of intermediate code into binary code within a binary code temporary memory location or buffer (107). The virtual machine (103) also has means for executing a binary version of an intermediate code, if it exists, in order to improve the performance of the application.
The use of a dynamic compiler however has two problems. First of all, a dynamic compiler takes time to get executed in addition to the application, both for determining hot spots and during the compilation of the intermediate code into binary code. Indeed, to identify the hot spots, an instrumentation of the interpreter of the virtual machine is generally done in order to monitor the behavior of the application. These steps of instrumentation consequently entail penalties for the performance of the application. As for the compilers, in order to limit their compilation time, the optimization done by them is simple and cannot be aggressive. This will limit the performance of the binary code generated relatively to the compiler which gets executed upstream to the execution. Then, these solutions use buffer memory to store the binary codes generated. In the majority of cases, this code is stored in a limited memory zone and the compiler must therefore make choices continuously in order to determine those binary codes that are the right ones to be kept in this buffer. This causes a problem of performance of these dynamic compilers when they manage numerous applications or when the size of this memory zone is small.
Thus, the dynamic compilers, although they generate binary code, cannot be used to achieve high levels of performance. Furthermore, the greater the importance of the intermediate code (as is the case on an Android™ application where the system service applications and the programming interfaces are executed in intermediate code), the more difficult it is to detect the hot spot, and the greater the extent to which the code buffer management is called into play, thus limiting the performance of the system correspondingly.
The second technique for optimizing the performance of the intermediate code consists in making the virtual machine faster on the chosen target. This optimizing can be done by optimizing the virtual machine for which it exploits the capacities of the processor that uses it to the greatest possible extent. It can also be done through an additional specific hardware support. It can also be done by designing a specific algorithm to raise the performance of the virtual machine on the target.
Apart from these two solutions, there remains the possibility of using an offline compiler which compiles the totality of the source code or the intermediate code into binary code upstream to the execution of the application. This approach makes it possible to avoid penalizing the execution of the application as a result of the time taken up by the dynamic compiler, and also enables the performance of highly optimized compilations of the application. This approach has the advantage of procuring high performance levels for the applications. This approach however dictates the complete compilation of an application and uses the operating system to control the execution of the application. In environments where the virtual machine is the execution core of the system, as is the case for the Android™ system, this makes it unusable because this solution is not planned for integration into a virtual machine. Besides, since the size of the binary code generated is greater than the size of the interpreted code, the size of the application becomes great and involves the use of more memory.